﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using MongoServices.Tests.TestHelpers;
using MongoServices.Tests.Stubs;

namespace MongoServices.Tests.MongoServicesModelTests
{
	public class AuditFieldsTests : TestBase
	{
		protected ReadWriteRepositoryTestModelSimpleStub Repository { get; private set; }

		public AuditFieldsTests()
		{
			Setup();
		}

		private void Setup()
		{
			Repository = new ReadWriteRepositoryTestModelSimpleStub();
		}
	}

	public class WhenADocumentIsInitiallySaved : AuditFieldsTests
	{
		[Fact]
		public void DateCreatedWillBeCloseToTheCurrentDateTime()
		{
			var model = new TestModelSimple();

			Repository.Save(model);

			var retrievedModels = CollectionTestModelSimple.FindAllAs<TestModelSimple>();

			Assert.Equal(1, retrievedModels.Count());
			Assert.InRange(retrievedModels.First().DateCreated, DateTime.UtcNow.AddSeconds(-10), DateTime.UtcNow);
		}

		[Fact]
		public void DateModifiedWillBeCloseToTheCurrentDateTime()
		{
			var model = new TestModelSimple();

			Repository.Save(model);

			var retrievedModels = CollectionTestModelSimple.FindAllAs<TestModelSimple>();

			Assert.Equal(1, retrievedModels.Count());
			Assert.InRange(retrievedModels.First().DateModified, DateTime.UtcNow.AddSeconds(-10), DateTime.UtcNow);
		}

		[Fact]
		public void DateCreatedWillNotBeTheDefaultDateTime()
		{
			var model = new TestModelSimple();

			Repository.Save(model);

			var retrievedModels = CollectionTestModelSimple.FindAllAs<TestModelSimple>();

			Assert.Equal(1, retrievedModels.Count());
			Assert.NotEqual(default(DateTime), retrievedModels.First().DateCreated);
		}

		[Fact]
		public void DateModifiedWillNotBeTheDefaultDateTime()
		{
			var model = new TestModelSimple();

			Repository.Save(model);

			var retrievedModels = CollectionTestModelSimple.FindAllAs<TestModelSimple>();

			Assert.Equal(1, retrievedModels.Count());
			Assert.NotEqual(default(DateTime), retrievedModels.First().DateModified);
		}

		[Fact]
		public void DateCreatedAndDateModifiedWillBeSetToSameValue()
		{
			var model = new TestModelSimple();

			Repository.Save(model);

			var retrievedModels = CollectionTestModelSimple.FindAllAs<TestModelSimple>();

			Assert.Equal(1, retrievedModels.Count());
			Assert.Equal(retrievedModels.First().DateCreated, retrievedModels.First().DateModified);
		}
	}

	public class WhenADocumentIsSavedASecondTime : AuditFieldsTests
	{
		[Fact]
		public void DateCreatedAndDateModifiedWillBeDifferent()
		{
			var model = new TestModelSimple();

			Repository.Save(model);

			var retrievedModelsInitialRetrieve = CollectionTestModelSimple.FindAllAs<TestModelSimple>();
			var retrievedModelInitialRetrieve = retrievedModelsInitialRetrieve.First();

			Repository.Save(retrievedModelInitialRetrieve);

			var retrievedModelsSecondRetrieve = CollectionTestModelSimple.FindAllAs<TestModelSimple>();

			Assert.Equal(1, retrievedModelsSecondRetrieve.Count());
			Assert.NotEqual(retrievedModelsSecondRetrieve.First().DateCreated, retrievedModelsSecondRetrieve.First().DateModified);
		}

		[Fact]
		public void DateModifiedWillBeCloseToTheCurrentDateTime()
		{
			var model = new TestModelSimple();

			Repository.Save(model);

			var retrievedModelsInitialRetrieve = CollectionTestModelSimple.FindAllAs<TestModelSimple>();
			var retrievedModelInitialRetrieve = retrievedModelsInitialRetrieve.First();

			Repository.Save(retrievedModelInitialRetrieve);

			var retrievedModelsSecondRetrieve = CollectionTestModelSimple.FindAllAs<TestModelSimple>();

			Assert.Equal(1, retrievedModelsSecondRetrieve.Count());
			Assert.InRange(retrievedModelsSecondRetrieve.First().DateModified, DateTime.UtcNow.AddSeconds(-10), DateTime.UtcNow);
		}
	}
}
